/**
 * 类：定义事物的抽象特点
 * 对象：类的实例
 * 面向对象：封装、继承、多态
 */
// 封装
class Animal {
  type: string;
  constructor(type: string) {
    this.type = type
  }
  run() {
    console.log(`${this.type} is running`)
  }
}

const rabbit = new Animal('rabbit')
// 继承
class Cat extends Animal {
  say() {
    console.log(`${this.type} is miao miao miao`);
  }
}

class Dog extends Animal {
  constructor(type) {
    super(type)
    console.log(this.type)
  }
  // 多态：重写父类方法
  run() {
    console.log(`${this.type} is running and barking`)
  }
}
// 安装 ts-node 通过ts-node运行代码
rabbit.run() // rabbit is running

const cat = new Cat('cat')
cat.say() // cat is miao miao miao
cat.run() // cat is running
const dog = new Dog('dog')
dog.run() // dog is running and barking

// 三种访问修饰符：public、protected、private

class Student {
  // 静态属性
  static categories: string[] = ['pupil', 'junior', 'senior', 'university']
  // 静态方法
  static isStudent(a) {
    if (a instanceof Student) {
      return true
    } else {
      return false
    }
  }
  readonly id: number;
  public name: string;
  protected gender: string;
  private phone: number;
  constructor(id: number, name: string, gender: string, phone: number) {
    this.id = id
    this.name = name
    this.gender = gender
    this.phone = phone
  }
  showPhone() {
    console.log(`${this.name} phone number is ${this.phone}`);
  }
}
console.log(Student.categories)
class Girl extends Student{
  constructor(id, name, gender, phone) {
    super(id, name, gender, phone)
  }
  showGender() {
    console.log(`${this.name} is ${this.gender}`)
  }
  // 报错子类不能访问到private
  // testShowPhone() {
  //   console.log(`${this.name} phone number is ${this.phone}`);
  // }
}

const xd = new Student(1, 'XD', 'female', 13012345678)
console.log(xd.id)
console.log(xd.name)
// console.log(xd.age) // 报错：只能在类“Student”及其子类中访问
// console.log(xd.phone) // 报错：只能在类“Student”中访问
xd.showPhone()
const xd2 = new Girl(1, 'XD', 'female', 13012345678)
xd2.showGender()
// 只读属性不可以重新赋值
// xd.id = 1 // 报错
// xd2.id = 2 // 报错
console.log(Student.isStudent(xd)) // true
console.log(Student.isStudent(xd2)) // true
console.log(Student.isStudent('123')) // false